using System;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using Object = UnityEngine.Object;

/****************************************************
// 功能：UI管理器
// | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
// | Copyright (c) 2021-2025 聊来 All rights reserved.
// | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">聊来</a> )
// | @Author: 贯彻己道的云 <18970881148@qq.com>
// | DateTime: 2025/2/14 15:44:32
*****************************************************/
public class UIManager : SingletonPatternBase<UIManager>
{
    // UI窗口根节点
    private Transform uiRoot;

    // 缓存窗口字典
    public Dictionary<WindowName, BaseWindow> dicWindows = new Dictionary<WindowName, BaseWindow>();

    // 已经打开窗口栈的信息
    private readonly Stack<WindowName> stackOpen = new Stack<WindowName>();

    // 配置信息的枚举
    public Dictionary<WindowName, WindowConfig> dicWindowConfig = new Dictionary<WindowName, WindowConfig>();

    // 当前打开的窗口ID
    private WindowName currentWindowId;
    
    public void Init(Transform uiRoot, List<WindowConfig> list)
    {
        this.uiRoot = uiRoot;

        // 销毁已经创建的UI窗口
        foreach (var item in dicWindows.Keys)
        {
            DestoryWindow(item);
        }

        ClearRecord();
        dicWindowConfig.Clear();
        // 添加新的配置
        foreach (var item in list)
        {
            dicWindowConfig[item.windowName] = item;
        }
    }

    public BaseWindow Open(WindowName windowId, object arg = null)
    {
        // 如果当前已经打开了，就不执行open操作
        if (currentWindowId != windowId)
        {
            CheckStackRecord(windowId);
            BaseWindow uiBase;
            if (currentWindowId != WindowName.None)
            {
                uiBase = GetUiWindow(currentWindowId);
                uiBase.SetWindowsState(currentWindowId, dicWindowConfig[currentWindowId].destroy);
            }

            // 打开新的窗口
            uiBase = GetUiWindow(windowId);
            uiBase.Open(arg);
            currentWindowId = windowId;
            return uiBase;
        }

        return null;
    }
    
    /// <summary>
    /// 把不需要的窗口回收掉
    /// </summary>
    public void GC()
    {
        List<WindowName> willRemoveList = new List<WindowName>();

        foreach (var item in dicWindows)
        {
            if (currentWindowId != item.Key)
            {
                willRemoveList.Add(item.Key);
            }
        }
        // 销毁标记为要移除的窗口
        foreach (var windowName in willRemoveList)
        {
            DestoryWindow(windowName);
        }
    }

    
    /// <summary>
    /// 开启一个弹窗
    /// </summary>
    /// <param name="id"></param>
    /// <param name="arg"></param>
    /// <returns></returns>
    public BaseWindow PopUp(WindowName id, object arg)
    {
        BaseWindow uiBase = GetUiWindow(id);
        uiBase.Open(arg, true);
        
        return uiBase;
    }

    /// <summary>
    /// 关闭弹出窗口
    /// </summary>
    /// <param name="id"></param>
    public void ClosePopUp(WindowName id)
    {
        BaseWindow uiBase = GetUiWindow(id);
        if (uiBase.isPop)
        {
            DestoryWindow(id);
        }
    }


    /// <summary>
    /// 跳转窗口，关闭之后，会还原之前的窗口
    /// </summary>
    /// <param name="id"></param>
    /// <param name="arg"></param>
    /// <returns></returns>
    public BaseWindow jump(WindowName id, object arg)
    {
        if (currentWindowId != id)
        {
            CheckStackRecord(id);
            BaseWindow uiBase;
            if (currentWindowId != WindowName.None)
            {
                // 关闭当前窗口
                uiBase = GetUiWindow(currentWindowId);
                uiBase.SetWindowsState(currentWindowId,false);
            }
            // 把当前的窗口压入堆栈
            stackOpen.Push(currentWindowId);

            // 打开新的窗口
            uiBase = GetUiWindow(id);
            uiBase.Open(arg);
            currentWindowId = id;
            return uiBase;
        }

        return null;
    }

    /// <summary>
    /// 销毁窗口
    /// </summary>
    /// <param name="name"></param>
    public void DestoryWindow(WindowName name)
    {
        
        if (dicWindows.TryGetValue(name, out var baseWindow))
        {
            Object.Destroy(baseWindow.gameObject);
            dicWindows.Remove(name);
        }
    }

    /// <summary>
    /// 清除掉已经打开的栈信息
    /// </summary>
    private void ClearRecord()
    {
        stackOpen.Clear();
    }


    /// <summary>
    /// 检查窗口ID是否在堆栈中重复
    /// </summary>
    /// <param name="windowId"></param>
    /// <returns></returns>
    private bool CheckStackRecord(WindowName windowId)
    {
        if (stackOpen.Contains(windowId))
        {
            return true;
        }
        return false;
    }
    
    /// <summary>
    /// 通过枚举拿到界面，或者新建一个
    /// </summary>
    /// <param name="windowId"></param>
    /// <returns></returns>
    public BaseWindow GetUiWindow(WindowName windowId)
    {
        
        if (!dicWindows.TryGetValue(windowId, out var uiBase))
        {
            //从资源中加载UI预制体
            string prefabPath = "Prefab/Window/" + Enum.GetName(typeof(WindowName), windowId) + "Window";
            BaseWindow prefab = Resources.Load<BaseWindow>(prefabPath);
            
            uiBase = Object.Instantiate(prefab, uiRoot, false);

            //初始化UI窗口
            uiBase.SetWindowsState(windowId,true, CloseHandle);
            dicWindows[windowId] = uiBase;
        }
        return uiBase;
    }
    
    /// <summary>
    /// 关闭窗口的回调函数
    /// </summary>
    /// <param name="windowId"></param>
    public void CloseHandle(WindowName windowId)
    {

        // 弹出上一个窗口，或者弹出主界面
        if (currentWindowId == windowId)
        {
            //Debug.Log("当前栈堆数量：" + stackOpen.Count);
            if (stackOpen.Count > 0)
            {
                //从堆栈中弹出上一个窗口id
                windowId = stackOpen.Pop();
            }
            else
            {
                //如果堆栈为空，打开主界面；
                windowId = WindowName.Login;
            }

            BaseWindow uiBase = GetUiWindow(windowId);
            uiBase.Open(null);
            currentWindowId = windowId;
        }
    }

    public void ShowTips(string str)
    {
        PopUp(WindowName.Tips, str);
    }
}